package io.jft.doll.weidget

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.Gravity
import android.view.Surface
import android.view.TextureView
import android.view.View
import android.widget.FrameLayout
import com.g.base.extend.dp
import com.g.base.extend.mainIoSchedulers
import io.jft.doll.R
import io.reactivex.Observable


/**
 * Created by G on 2017/12/31 0031.
 */
class LoadingVideoSurface : FrameLayout {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    private val textureView = TextureView(context)
    private val renderWhatView = io.jft.doll.weidget.RenderWhatView(context)
    private var surface: Surface? = null

    init {
        addView(textureView)
        addView(renderWhatView)

        setBackgroundResource(R.drawable.img_room_loading)

        val layoutParams1 = textureView.layoutParams as FrameLayout.LayoutParams
        layoutParams1.gravity = Gravity.CENTER
        layoutParams1.width = FrameLayout.LayoutParams.MATCH_PARENT
        layoutParams1.height = FrameLayout.LayoutParams.MATCH_PARENT
        textureView.layoutParams = layoutParams1

        val layoutParams2 = renderWhatView.layoutParams as FrameLayout.LayoutParams
        layoutParams2.gravity = Gravity.CENTER
        layoutParams2.height = 40.dp()
        layoutParams2.width = 64.dp()
        renderWhatView.layoutParams = layoutParams2
    }

    fun getSurface(): Observable<Surface> {
        surface?.release()
        return Observable.create<Surface> {
            if (textureView.isAvailable) {
                surface = Surface(textureView.surfaceTexture)
                it.onNext(surface!!)
                it.onComplete()
            } else {
                textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
                    override fun onSurfaceTextureSizeChanged(p0: SurfaceTexture?, p1: Int, p2: Int) {}

                    override fun onSurfaceTextureDestroyed(p0: SurfaceTexture?): Boolean {
                        return true
                    }

                    override fun onSurfaceTextureUpdated(p0: SurfaceTexture?) {
                    }

                    override fun onSurfaceTextureAvailable(p0: SurfaceTexture?, p1: Int, p2: Int) {
                        textureView.surfaceTextureListener = null
                        surface = Surface(textureView.surfaceTexture)
                        it.onNext(surface!!)
                        it.onComplete()
                    }
                }
            }
        }.mainIoSchedulers()
    }

    fun release() {
        surface?.release()
        renderWhatView.release()
    }

    fun showLoading() {
        renderWhatView.showLoading()
    }

    fun showError() {
        renderWhatView.showError()
    }

    fun showStop() {
        renderWhatView.showStop()
    }

    fun showNothing() {
        renderWhatView.showNothing()
    }

    fun stopRender() {
        renderWhatView.stopRender()
    }

    fun startRender() {
        renderWhatView.startRender()
    }
}


private class RenderWhatView : View {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    private val paint: Paint = Paint()
    private val animatorSet: AnimatorSet
    private var rendWhat = RenderWhatEnum.NOTHING

    private val scale = 1.0f
    private var scaleFloats = floatArrayOf(scale, scale, scale, scale)

    init {
        paint.color = Color.WHITE
        paint.isAntiAlias = true
        paint.style = Paint.Style.FILL

        animatorSet = AnimatorSet()
        val animatorList = arrayListOf<Animator>()
        val durations = longArrayOf(1260 * 2, 430 * 2, 1010 * 2, 730 * 2)
        val delays = longArrayOf(770, 290, 280, 740)
        for (i in 0..3) {
            val scaleAnim = ValueAnimator.ofFloat(1f, 0.4f, 1f)
            scaleAnim.duration = durations[i]
            scaleAnim.repeatCount = -1
            scaleAnim.startDelay = delays[i]
            scaleAnim.addUpdateListener {
                scaleFloats[i] = it.animatedValue as Float
                invalidate()
            }
            animatorList.add(scaleAnim)
        }
        animatorSet.playTogether(animatorList)
        animatorSet.start()
        animatorSet.pause()
    }

    fun release() {
        animatorSet.end()
    }

    fun showLoading() {
        animatorSet.resume()
        rendWhat = RenderWhatEnum.LOADING
        invalidate()
    }

    fun showError() {
        animatorSet.pause()
        rendWhat = RenderWhatEnum.ERROR
        invalidate()
    }

    fun showStop() {
        animatorSet.pause()
        rendWhat = RenderWhatEnum.STOP
        invalidate()
    }

    fun showNothing() {
        animatorSet.pause()
        rendWhat = RenderWhatEnum.NOTHING
        invalidate()
    }

    fun stopRender() {
        animatorSet.pause()
        invalidate()
    }

    fun startRender() {
        if (rendWhat == RenderWhatEnum.LOADING)
            animatorSet.resume()
        invalidate()
    }

    override fun onDraw(canvas: Canvas?) {
        canvas ?: return
        when (rendWhat) {
            RenderWhatEnum.LOADING -> {
                rendLoading(canvas)
            }
            RenderWhatEnum.ERROR -> {
                rendError(canvas)
            }
            RenderWhatEnum.STOP -> {
                rendStop(canvas)
            }
            RenderWhatEnum.NOTHING -> {
                canvas.drawColor(Color.TRANSPARENT)
            }
        }
    }

    private fun rendLoading(canvas: Canvas) {
        val vh = 40.dp()
        val vw = 64.dp()
        val dp8 = 8.dp().toFloat()

        canvas.translate(0f, vh / 2f)
        val translateX = vw / 9f
        for (i in 0..3) {
            canvas.save()
            canvas.translate((2f + i * 2f) * translateX - translateX / 2f, 0f)
            canvas.scale(scaleFloats[i], scaleFloats[i])
            val rectF = RectF(-translateX / 2f, -vh / 2f, translateX / 2f, vh / 2f)

            canvas.drawRoundRect(rectF, dp8, dp8, paint)
            canvas.restore()
        }
    }

    private fun rendStop(canvas: Canvas) {
        val vhw = 36.dp()

        canvas.translate((width - vhw) / 2f, (height - vhw) / 2f)
        val drawable = resources.getDrawable(R.drawable.ic_play_circle_outline_white_24dp)
        drawable.setBounds(0, 0, vhw, vhw)
        drawable.draw(canvas)
    }

    private fun rendError(canvas: Canvas) {
        val vhw = 36.dp()

        canvas.translate((width - vhw) / 2f, (height - vhw) / 2f)
        val drawable = resources.getDrawable(R.drawable.ic_error_outline_white_24dp)
        drawable.setBounds(0, 0, vhw, vhw)
        drawable.draw(canvas)
    }

}

enum class RenderWhatEnum(val v: Int) {
    NOTHING(0),
    LOADING(1),
    ERROR(2),
    STOP(3),
}